﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace LSA.OnlineResources
{
    public class BingSearch : ISearchEngine
    {
        public BingSearch(string searchExpression, WebProxy proxySettings)
        {
            Engine = SearchResult.SearchEngine.Bing;
            SearchExpression = searchExpression;
            if(client == null)
            {
                //ServicePointManager.MaxServicePoints = int.MaxValue;
                client = new WebClient {Encoding = System.Text.Encoding.UTF8, Proxy = proxySettings};
            }
        }
        
        public BingSearch(string searchExpression) : this(searchExpression, null)
        {
        }

        public SearchResult.SearchEngine Engine { get; set; }
        public string SearchExpression { get; set; }

        private static WebClient client;

        public List<SearchResult> Search()
        {
            const string urlTemplate =
                @"http://api.search.live.net/json.aspx?AppId=C2BC7D1732A3A24D8349BD85EEF6D588724A88BD&Sources=Web&Query={0}&Web.Count=50"; // TODO: add to config, add &Market=en-US
            const string offsetTemplate = "&Web.Offset={1}";
            var resultsList = new List<SearchResult>();
            int[] offsets = {0};
            Uri searchUrl;
            foreach (var offset in offsets)
            {
                searchUrl = offset == 0 ? new Uri(string.Format(urlTemplate, SearchExpression)) : new Uri(string.Format(urlTemplate + offsetTemplate, SearchExpression, offset));
                var page = client.DownloadString(searchUrl);
                var o = (JObject) JsonConvert.DeserializeObject(page);

                if (o["SearchResponse"] == null || !o["SearchResponse"].Any())
                {
                    throw new WebException("Bing returned nothing");
                }
                if (o["SearchResponse"]["Web"] == null || !o["SearchResponse"]["Web"].Any())
                {
                    throw new WebException("Bing returned nothing");
                }
                if (o["SearchResponse"]["Web"]["Results"] == null || !o["SearchResponse"]["Web"]["Results"].Any())
                {
                    throw new WebException("Bing returned nothing");
                }

                var children = o["SearchResponse"]["Web"]["Results"].Children();
                var resultsQuery = from result in children
                                   select
                                       new SearchResult
                                           {
                                               Url = result.Value<string>("Url"),
                                               Title = result.Value<string>("Title"),
                                               Content = result.Value<string>("Description"),
                                               Engine = Engine
                                           };
                resultsList.AddRange(resultsQuery);
            }
            return resultsList;
        }
    }
}
